Import Necessary Modules¶
In [1]:
from pathlib import Path
from ipyniivue import download_dataset
BASE_API_URL = "https://niivue.com/demos/images/"
DATA_FOLDER = Path("images")
# Download data for example
download_dataset(
BASE_API_URL,
dest_folder=DATA_FOLDER,
files=[
"mni152.nii.gz",
"aal.nii.gz",
"aal.json",
],
)
mni152.nii.gz already exists. Downloading aal.nii.gz...
Downloading aal.json... Dataset downloaded successfully to images.
In [2]:
import json
import ipywidgets as widgets
from IPython.display import display
from ipyniivue import NiiVue, ShowRender
# Create NiiVue Instance
nv = NiiVue(
show_3d_crosshair=True,
back_color=(0.5, 0.5, 0.5, 1),
)
nv.set_interpolation(True)
nv.opts.crosshair_gap = 12
nv.opts.multiplanar_show_render = ShowRender.ALWAYS
nv.opts.drag_mode = "PAN"
nv.opts.yoke_3d_to_2d_zoom = True
nv.load_volumes(
[
{"path": DATA_FOLDER / "mni152.nii.gz"},
{"path": DATA_FOLDER / "aal.nii.gz"},
]
)
# Load colormap label
with open(DATA_FOLDER / "aal.json") as f:
cmap = json.load(f)
nv.volumes[1].set_colormap_label(cmap)
clut = nv.volumes[1].colormap_label.lut.copy()
# Make all regions translucent by setting alpha values to 96
for i in range(3, len(clut), 4):
clut[i] = 96
# Update the colormap label with the modified lut
nv.volumes[1].colormap_label.lut = clut
# Add other widgets
interp_checkbox = widgets.Checkbox(
value=True,
description="Jagged",
)
outline_slider = widgets.IntSlider(
min=0,
max=255,
value=1,
description="Outline",
)
alpha_slider = widgets.IntSlider(
min=1,
max=255,
value=150,
description="Opacity",
)
pad_slider = widgets.IntSlider(
min=0,
max=10,
value=5,
description="Padding",
)
gap_slider = widgets.IntSlider(
min=0,
max=36,
value=12,
description="Crosshair Gap",
)
# Setup observer functions
def on_outline_change(change):
"""Handle changes in the outline slider."""
nv.set_atlas_outline(change["new"] / 255)
def on_alpha_change(change):
"""Handle changes in the opacity slider."""
nv.volumes[1].opacity = change["new"] / 255
def on_pad_change(change):
"""Handle changes in the padding slider."""
nv.opts.multiplanar_pad_pixels = change["new"]
def on_gap_change(change):
"""Handle changes in the crosshair gap slider."""
nv.opts.crosshair_gap = change["new"]
def on_interp_change(change):
"""Handle changes in the interpolation checkbox."""
nv.set_interpolation(change["new"])
# Observe changes
# Observe changes in widget values and call the respective functions
outline_slider.observe(on_outline_change, names="value")
alpha_slider.observe(on_alpha_change, names="value")
pad_slider.observe(on_pad_change, names="value")
gap_slider.observe(on_gap_change, names="value")
interp_checkbox.observe(on_interp_change, names="value")
# Initialize the NiiVue instance with the current widget values
on_alpha_change({"new": alpha_slider.value})
on_outline_change({"new": outline_slider.value})
nv.opts.multiplanar_pad_pixels = pad_slider.value
nv.opts.crosshair_gap = gap_slider.value
nv.set_interpolation(interp_checkbox.value)
# Setup hover and click updates
output = widgets.HTML("Hover:<br>Clicked:")
active_idx = -1
@nv.on_hover_idx_change
def on_hover_idx_change(data):
"""Handle hover updates."""
global active_idx
idx_values = data["idxValues"]
idx = idx_values[1]["idx"]
if idx is not None and idx != active_idx:
nv.opts.atlas_active_index = idx
label = cmap["labels"][idx] if idx < len(cmap["labels"]) else ""
clicked_line = output.value.split("Clicked:")[1]
output.value = f"Hover: {label}<br>Clicked:{clicked_line}"
@nv.on_location_change
def handle_location_change(location):
"""Handle mouse clicks."""
hover_line = output.value.split("Hover:")[1].split("<br>")[0]
output.value = f"Hover:{hover_line}<br>Clicked: {location['string']}"
# Display all
controls = widgets.VBox(
[
interp_checkbox,
outline_slider,
alpha_slider,
pad_slider,
gap_slider,
output,
]
)
display(
widgets.VBox(
[
controls,
nv,
]
)
)